In Ruby, moving beyond the happy path means transitioning from linear logic to a defensive posture where failures are treated as first-class objects rather than program-ending catastrophes.
1. The Exception Hierarchy
Ruby predefines a tidy hierarchy of exceptions shown in Figure 8.1. Every error is an instance of a class within this tree, starting at the Exception root. Understanding this tree is vital: application-level errors generally descend from StandardError, while system-level failures (like NoMemoryError) descend directly from Exception.
2. Errors as Data Objects
Unlike lower-level languages where an error might be a simple return code, Ruby packages context—including the message string and the execution backtrace—into a formal object. This allows developers to treat runtime interruptions as data that can be inspected and managed through inheritance.